/**
 * 
 */
package com.java8.lambda;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 函数式接口demo
 * 
 * @author zhangyang
 *
 */
public class FunctionalInterfaceTest {

	//@org.junit.Test
	public void Test() {
		/**
		 * 需求 对两个数进行运算 但是不指定运算函数 
		 * 这个可以用策略模式或者解释器模式来实现 但是代码比较多 现在用java8的函数式接口实现
		 */
		Integer operation = operation(100,null, (x,y) -> x * 2+y);
		System.out.println("操作结果是==" + operation);
	}

	/**
	 * java8内置的4大函数式接口
	 */
	@org.junit.Test
	public void test1() {
		/**
		 * Consumer-消费型接口 有参数无返回值
		 */
		shopping(1000D, x->System.out.println("大保健，每次消费"+x));
		/**
		 * 供给型接口 -无参数有返回值
		 * 产生一些随机数字并且放入到集合中
		 */ 
		List<Integer> addEmpl = addList(5, ()->(int)(Math.random()*100));
		System.out.println(addEmpl);
		/**
		 * 函数型接口-有参数有返回值
		 * 对字符串做截取处理 不确定捷区范围
		 */
		String string = StringHandler("这是要截取的字符串", x->x.substring(2, 5));
		System.out.println(string);
		
		/**
		 * 判断型接口-接口返回值是boolean类型
		 * 将符合长度的字符串放入集合中
		 */
		List<String> list1=Arrays.asList("1","1212121","1212","2");
		List<String> handler = ListHandler(list1,x->x.length()>3);
		System.out.println(handler);
	}
	
	public Integer operation(Integer x,Integer y, CalculateInterface inter) {
		//在接口里面写了非空判断的default方法，这样就能做非空判断 可以直接调用
		 x = inter.ifNull(x);
		 y = inter.ifNull(y);
		 //这是接口的static方法，和类的静态方法一样，也能直接被调用
		 int compare = CalculateInterface.compare(x, y);
		 System.out.println("x和Y的比较==="+compare);
		return inter.calculate(x,y);
	}
	
	/**
	 * Consumer接口-有去无回 有参数无返回值
	 * @param money
	 * @param comsumer
	 */
	public void shopping(Double money,Consumer<Double> comsumer) {
		comsumer.accept(money);
	}
	/**
	 * supplier接口 无参数有返回值
	 * @param num
	 * @param sup
	 * @return
	 */
	public List<Integer> addList(int num,Supplier<Integer> sup) {
		List<Integer> list=new ArrayList<>();
		for(int i=0;i<num;i++) {
			Integer employee = sup.get();
			list.add(employee);
		}
		return list;
	}
	
	/**
	 * Function接口 有参数返回值
	 * @param str
	 * @param func
	 * @return
	 */
	public String StringHandler(String str,Function<String,String> func) {
		return func.apply(str);
	}
	/**
	 * Predicate 接口 按照参数条件获取Boolean类型的返回值
	 * @param list
	 * @param pre
	 * @return
	 */
	public List<String> ListHandler(List<String> list,Predicate<String> pre){
		List<String> res=new ArrayList<>();
		for(String str:list) {
			if(pre.test(str)) {
				res.add(str);
			}
		}
		return res;
	}
}

/**
 * 函数式接口-运算符函数
 * 特点1只能写一个抽象方法 -equals例外
 * 特点2 default关键字
 * default代表这个方法接口的默认方法，也就是说接口里面也能写具体方法
 * 这样在调用时就能直接调用接口里面方法
 * 特点3 static关键字
 * static关键字修饰接口里面的方法，这个方法和类当中静态方法一样类名.方法名可以直接调用
 * @author zhangyang
 *
 */
@FunctionalInterface
interface CalculateInterface {
	public Integer calculate(Integer x,Integer y);
	boolean equals(Object obj);
	default public Integer ifNull(Object obj) {
		if(obj==null || "".equals(obj))
			return 0;
		else 
			return Integer.parseInt(obj.toString());
	}
	public static int compare(Integer x,Integer y) {
		return Integer.compare(x, y);
	}
}